<?php

/**
 * Root class of all entity classes. Provided basic data manipulation API used
 * by the Persistence class.
 */
abstract class Entity {
    private $primaryKey;
    private $primaryKeyType;
    private $reflection;
    private $tableName;
    
    /**
     * Initializes the Entity. This should be executed by implementing class'es
     * constructor. The implementing class'es construct is supposed to be
     * parameter-less.
     * 
     * @param string $primaryKey Name of the primary key field.
     * @param string $primaryKeyType Dibi type of primary key field (to use in
     *        dibi SQL).
     * @param array $data Data to be set to the new entity.
     */
    protected function __construct($primaryKey, $primaryKeyType,
            array $data = array()) {
        $this->primaryKey = $primaryKey;
        $this->primaryKeyType = $primaryKeyType;
        $this->reflection = new ReflectionObject($this);
        $this->load($data);
    }
    
    /**
     * Returns the database table name. This is also the class name.
     * 
     * @return string Database table name.
     */
    public function getTable() {
        if ($this->tableName) {
            return $this->tableName;
        }
        $this->tableName = preg_replace('/Entity$/', '',
                $this->reflection->getName());
        return $this->tableName;
    }
    
    /**
     * Creates a dump of this entity's data.
     * 
     * @return array Dump of this entity's data.
     */
    public function dump() {
        $data = array();
        $fields = $this->reflection->getProperties(
                ReflectionProperty::IS_PUBLIC);
        foreach ($fields as $field) {
            $name = $field->getName();
            $data[$name] = $this->$name;
        }
        return $data;
    }
    
    /**
     * Loads the provided data to this entity.
     * 
     * @param array $data The data to load.
     */
    public function load(array $data) {
        $fields = $this->reflection->getProperties(
                ReflectionProperty::IS_PUBLIC);
        foreach ($fields as $field) {
            $name = $field->getName();
            if (isset($data[$name])) {
                $this->$name = $data[$name];
            }
        }
    }
    
    /**
     * Returns the name of the primary key field.
     * 
     * @return string Primary key field's name.
     */
    public function getPKField() {
        return $this->primaryKey;
    }
    
    /**
     * Returns Dibi-compatible field type specification, without the starting %
     * symbol.
     * 
     * @return string Dibi-compatible field type specification.
     */
    public function getPKFieldDibiType() {
        return $this->primaryKeyType;
    }
}
